/*
 * Project: Daycare Web Application
 * Package: com.madetoordersoftware.daycare.control
 * File:    ChildCtrl
 * Created: Jun 3, 2010
 */
/*
 *  Copyright (c) 2010 Made 2 Order Software, LLC
 *
 *  All rights reserved. No part of this software may be reproduced, stored in a retrieval system, or
 *  transmitted in any form or by any means, without the prior written permission of Made 2 Order Software.
 *
 *  You may not distribute the URL or redistribute the files to third parties. You may transfer the files
 *  onto a single storage device so long as you can prove ownership of the software. You may not reverse
 *  engineer, decompile, or disassemble the software or media files. You may not modify or translate the
 *  software or media, or distribute copies of the software or media without the written consent of Made
 *  2 Order Software
 */
package com.made2ordersoftware.daycare.control;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.made2ordersoftware.control.AbstractCtrl;
import com.made2ordersoftware.daycare.business.ReportMgr;
import com.made2ordersoftware.daycare.control.util.JsfUtil;
import com.made2ordersoftware.daycare.domain.TimeWatchedEntity;
import com.made2ordersoftware.daycare.service.exceptions.IncorrectReportTypeException;
import com.made2ordersoftware.exceptions.DAOException;
import com.made2ordersoftware.util.ExceptionHandler;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import javax.enterprise.context.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Class description
 *
 * @author David Canning <dcannin@gmail.com>
 * @version 1.0.0.0
 *
 */
@Named("report")
@RequestScoped
public class ReportCtrl extends AbstractCtrl {

    private static final Logger LOG = LoggerFactory.getLogger(ReportCtrl.class);
    private static final int BUFFER_SIZE = 10240;
    private long childId;
    private long parentId;
    private List<TimeWatchedEntity> report = new ArrayList<>();
    private Date startDate;
    private Date stopDate;
    @Inject
    private ReportMgr manager;

    /**
     * Default constructor to create instance of <code>ReportCtrl</code>.
     */
    public ReportCtrl() {
    }

    /**
     * Generates a report for all children within the specified dates.
     *
     * @return
     *
     */
    public String createReportByDates() {
        LOG.info("Creating report by dates.");

        String nextPage = null;
        Exception exp = null;
        String message = null;

        try {
            Document doc = manager.generateDateReport(new Timestamp(getStartDate().getTime()), new Timestamp(
                    getStopDate().getTime()));
            displayReport(doc);
            nextPage = "/home";
        } catch (DAOException | IncorrectReportTypeException | DocumentException | FileNotFoundException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } catch (IOException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } finally {
            if (exp != null) {
                ExceptionHandler.handleException(exp);
                JsfUtil.addErrorMessage(message);
            } else {
                JsfUtil.addSuccessMessage(message);
            }
        }

        return nextPage;
    }

    /**
     * Generates a report for all children within the specified dates.
     *
     * @return
     *
     */
    public String createReportByAge() {
        LOG.info("Creating report by age.");

        String nextPage = null;
        Exception exp = null;
        String message = null;

        try {
            Document doc = manager.generateAgeReport(new Timestamp(getStartDate().getTime()), new Timestamp(
                    getStopDate().getTime()));
            displayReport(doc);
            nextPage = "/home";
        } catch (DAOException | IncorrectReportTypeException | DocumentException | FileNotFoundException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } catch (IOException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } finally {
            if (exp != null) {
                ExceptionHandler.handleException(exp);
                JsfUtil.addErrorMessage(message);
            } else {
                JsfUtil.addSuccessMessage(message);
            }
        }
        return nextPage;
    }

    /**
     * Generates a report for all children of the specified parent.
     *
     * @return
     *
     */
    public String createReportByParent() {
        LOG.info("Creating report by parent.");

        String nextPage = null;
        Exception exp = null;
        String message = null;

        try {
            Document doc = manager.generateParentReport(new Timestamp(getStartDate().getTime()),
                    new Timestamp(getStopDate().getTime()), getParentId());
            displayReport(doc);
            nextPage = "/home";
        } catch (DAOException | IncorrectReportTypeException | DocumentException | FileNotFoundException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } catch (IOException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } finally {
            if (exp != null) {
                ExceptionHandler.handleException(exp);
                JsfUtil.addErrorMessage(message);
            } else {
                JsfUtil.addSuccessMessage(message);
            }
        }
        return nextPage;
    }

    /**
     * Generates a report for the specified child.
     *
     * @return
     *
     */
    public String createReportByChild() {
        LOG.info("Creating report by child.");

        String nextPage = null;
        Exception exp = null;
        String message = null;

        try {
            Document doc = manager.generateChildReport(new Timestamp(getStartDate().getTime()),
                    new Timestamp(getStopDate().getTime()), getChildId());
            displayReport(doc);
            nextPage = "/home";
        } catch (DAOException | IncorrectReportTypeException | DocumentException | FileNotFoundException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } catch (IOException e) {
            exp = e;
            message = ResourceBundle.getBundle("/Bundle").getString("persistence_error_occured");
            nextPage = "serverError";
        } finally {
            if (exp != null) {
                ExceptionHandler.handleException(exp);
                JsfUtil.addErrorMessage(message);
            } else {
                JsfUtil.addSuccessMessage(message);
            }
        }
        return nextPage;
    }

    /**
     *
     * @param document
     */
    private void displayReport(Document document) throws FileNotFoundException, IOException {
        ExternalContext externalContext = getFacesContext().getExternalContext();
        HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

        File file = new File("daycareReport.pdf");

        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            input = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);

            // Init servlet response.
            response.reset();
            response.setHeader("Content-Type", "application/pdf");
            response.setHeader("Content-Length", String.valueOf(file.length()));
            response.setHeader("Content-Disposition", "inline; filename=daycareReport.pdf" + "\"");

            output = new BufferedOutputStream(response.getOutputStream(), BUFFER_SIZE);

            // Write file contents to response.
            byte[] buffer = new byte[BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            output.flush();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                }
            }
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                }
            }
        }

        // Inform JSF that it doesn't need to handle response.
        // This is very important, otherwise you will get the following exception in the logs:
        // java.lang.IllegalStateException: Cannot forward after response has been committed.
        getFacesContext().responseComplete();
    }

    /**
     * @return the childId
     */
    public long getChildId() {
        return childId;
    }

    /**
     * @param childId the childId to set
     */
    public void setChildId(long childId) {
        this.childId = childId;
    }

    /**
     * @return the parentId
     */
    public long getParentId() {
        return parentId;
    }

    /**
     * @param parentId the parentId to set
     */
    public void setParentId(long parentId) {
        this.parentId = parentId;
    }

    /**
     * @return the report
     */
    public List<TimeWatchedEntity> getReport() {
        return Collections.unmodifiableList(report);
    }

    /**
     * @param report the report to set
     */
    public void setReport(List<TimeWatchedEntity> report) {
        this.report = report;
    }

    /**
     * @return the startDate
     */
    public Date getStartDate() {
        return startDate;
    }

    /**
     * @param startDate the startDate to set
     */
    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    /**
     * @return the stopDate
     */
    public Date getStopDate() {
        return stopDate;
    }

    /**
     * @param stopDate the stopDate to set
     */
    public void setStopDate(Date stopDate) {
        this.stopDate = stopDate;
    }

}
